package com.ruoyi.system.en;


import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.system.domain.OperateDBDTO;
import com.ruoyi.system.domain.OperateStructureDTO;
import com.ruoyi.system.domain.SaveColumnDTO;
import com.ruoyi.system.service.DSTypeService;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author py
 * @Description: 数据源类型及驱动枚举
 */

@Slf4j
@Getter
@AllArgsConstructor
public enum DSType implements DSTypeService {
    DS_ORACLE("DS_ORACLE", "Oracle", "oracle.jdbc.driver.OracleDriver") {
        @Override
        public String getUrl(OperateDBDTO operateDBDTO) {
            String url = "jdbc:oracle:thin:@" + operateDBDTO.getIp() + ":" + operateDBDTO.getPort() + ":" + operateDBDTO.getSchemal();
            return url;
        }
    },
    DS_MYSQL("DS_MYSQL", "Mysql", "com.mysql.jdbc.Driver") {
        @Override
        public String getUrl(OperateDBDTO operateDBDTO) {
            String url = "jdbc:mysql://" + operateDBDTO.getIp() + ":" + operateDBDTO.getPort() + "/" + operateDBDTO.getSchemal() + "?useSSL=false&useUnicode=true&characterEncoding=UTF-8";
            return url;
        }
    },
    DS_HIVE("DS_HIVE", "hive", "org.apache.hive.jdbc.HiveDriver") {
        @Override
        public String getUrl(OperateDBDTO operateDBDTO) {
            String url = "jdbc:hive2://" + operateDBDTO.getIp() + ":" + operateDBDTO.getPort() + "/" + operateDBDTO.getSchemal();
            return url;
        }
    },
    DS_SQLSERVER("DS_SQLSERVER", "SQL server", "com.microsoft.sqlserver.jdbc.SQLServerDriver") {
        @Override
        public String getUrl(OperateDBDTO operateDBDTO) {
            String url = "jdbc:sqlserver://" + operateDBDTO.getIp() + ":" + operateDBDTO.getPort() + ";DatabaseName=" + operateDBDTO.getSchemal();
            return url;
        }
    },
    DS_HBASE("DS_HBASE", "hbase", "") {
        @Override
        public String getUrl(OperateDBDTO operateDBDTO) {
            return null;
        }
    },
    DS_DB2("DS_DB2", "db2", "com.ibm.db2.jcc.DB2Driver") {
        @Override
        public String getUrl(OperateDBDTO operateDBDTO) {
            String url = "jdbc:db2://" + operateDBDTO.getIp() + ":" + operateDBDTO.getPort() + "/" + operateDBDTO.getSchemal();
            return url;
        }
    };

    public static Connection getConnection(OperateDBDTO operateDBDTO) {
        try {
            Class.forName(operateDBDTO.getDriver());
            Properties props = new Properties();
            props.put("user", operateDBDTO.getUser());
            props.put("password", operateDBDTO.getPassword());
            props.put("useInformationSchema", "true");
            Connection connection = DriverManager.getConnection(operateDBDTO.getUrl(), props);
            return connection;
        } catch (ClassNotFoundException e) {
            log.error("数据库驱动加载失败, 提示: [{}]", e.getMessage());
        } catch (SQLException e) {
            log.error("数据库连接失败, 提示: [{}]", e.getMessage());
        }
        return null;
    }

    public static Map<String, OperateStructureDTO> getStructureDTO(OperateDBDTO operateDBDTO) {
        Connection connection = getConnection(operateDBDTO);
        if (connection == null) {
            throw new BaseException("数据源连接失败，无法同步");
        }


        Map<String, OperateStructureDTO> tableMap = new HashMap<>();
        try {
            DatabaseMetaData metaData = connection.getMetaData();

            ResultSet tablesRs = metaData.getTables(connection.getCatalog(), connection.getSchema(), null, new String[]{"TABLE"});
            while (tablesRs.next()) {
                String tableName = tablesRs.getString("TABLE_NAME");
                ResultSet columnsRs = metaData.getColumns(connection.getCatalog(), connection.getSchema(), tableName, null);
                Map<String, SaveColumnDTO> columnMap = new HashMap<>();
                while (columnsRs.next()) {
                    SaveColumnDTO columnDTO = new SaveColumnDTO();
                    columnDTO.setColumnName(columnsRs.getString("COLUMN_NAME"));
                    columnDTO.setColumnComment(columnsRs.getString("REMARKS"));
                    columnDTO.setColumnType(columnsRs.getString("TYPE_NAME"));
                    columnDTO.setColumnLength(columnsRs.getString("COLUMN_SIZE"));
                    columnDTO.setIsPrimary("0");
                    columnMap.put(columnDTO.getColumnName(), columnDTO);
                }
                //主键
                ResultSet primaryRs = metaData.getPrimaryKeys(connection.getCatalog(), connection.getSchema(), tableName);
                while (primaryRs.next()) {
                    columnMap.get(primaryRs.getObject(4)).setIsPrimary("1");
                }
                OperateStructureDTO structureDTO = new OperateStructureDTO();
                structureDTO.setTableName(tableName);
                structureDTO.setTableComment(tablesRs.getString("REMARKS"));
                structureDTO.setColumnMap(columnMap);
                tableMap.put(tableName, structureDTO);
            }
        } catch (SQLException e) {
            log.error("获取数据库元数据失败, 提示: [{}]", e.getMessage());
            throw new BaseException("获取数据库元数据失败，无法同步");
        }

        try {
            connection.close();
        } catch (SQLException e) {
            log.error("关闭数据库失败, 提示: [{}]", e.getMessage());
        }

        return tableMap;
    }

    private String code;

    private String name;

    private String driverName;
}
